package com.feilong.edgeAI;

import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;


import com.alibaba.android.arouter.launcher.ARouter;
import com.baidu.location.LocationClient;
import com.facebook.common.internal.Supplier;
import com.facebook.common.util.ByteConstants;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.cache.MemoryCacheParams;
import com.facebook.imagepipeline.core.ImagePipelineConfig;
import com.feilong.edgeAI.ui.HomeActivity;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechUtility;
import com.tencent.bugly.crashreport.CrashReport;
import com.zlw.main.recorderlib.RecordManager;

import org.xutils.x;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class SpeechApp extends Application implements Thread.UncaughtExceptionHandler {

    private static final String TAG = "WebActivity";
    public static final String PRIVACY_KEY = "privacy_key";
    private static boolean mscInitialize = false;
    private static Context context;
    /**
     * 主线程ID
     */
    private static int mMainThreadId = -1;
    /**
     * 主线程ID
     */
    private static Thread mMainThread;
    /**
     * 主线程Handler
     */
    private static Handler mMainThreadHandler;
    /**
     * 主线程Looper
     */
    private static Looper mMainLooper;

    private static int MAX_MEM = 30 * ByteConstants.MB;
    @Override
    public void onCreate() {
        init();
        // 应用程序入口处调用,避免手机内存过小,杀死后台进程后通过历史intent进入Activity造成SpeechUtility对象为null
        // 注意：此接口在非主进程调用会返回null对象，如需在非主进程使用语音功能，请增加参数：SpeechConstant.FORCE_LOGIN+"=true"
        // 参数间使用“,”分隔。
        // 设置你申请的应用appid

        // 注意： appid 必须和下载的SDK保持一致，否则会出现10407错误

        super.onCreate();
        LocationClient.setAgreePrivacy(true);
        ARouter.openLog();     // Print log
        ARouter.openDebug();
        ARouter.init(this);//阿里路由初始化

        Fresco.initialize(this, getConfigureCaches(this));//图片加载框架初始化
        initBugly();
        x.Ext.init(this);
        x.Ext.setDebug(BuildConfig.DEBUG);
        context = this;
        Thread.setDefaultUncaughtExceptionHandler(this);
        RecordManager.getInstance().init(this, false);
//        hookWebView();
//        MultiDex.install(this);
    }

    private ImagePipelineConfig getConfigureCaches(Context context) {
        final MemoryCacheParams bitmapCacheParams = new MemoryCacheParams(
                MAX_MEM,// 内存缓存中总图片的最大大小,以字节为单位。
                Integer.MAX_VALUE,// 内存缓存中图片的最大数量。
                MAX_MEM,// 内存缓存中准备清除但尚未被删除的总图片的最大大小,以字节为单位。
                Integer.MAX_VALUE,// 内存缓存中准备清除的总图片的最大数量。
                Integer.MAX_VALUE);// 内存缓存中单个图片的最大大小。

        Supplier<MemoryCacheParams> mSupplierMemoryCacheParams = new Supplier<MemoryCacheParams>() {
            @Override
            public MemoryCacheParams get() {
                return bitmapCacheParams;
            }
        };
        ImagePipelineConfig.Builder builder = ImagePipelineConfig.newBuilder(context);
        builder.setBitmapMemoryCacheParamsSupplier(mSupplierMemoryCacheParams);
        return builder.build();
    }
    public static Context getInstance() {
        return context;
    }

    public void initBugly() {
        String versionName = null;
        PackageManager manager = getPackageManager();
        try {
            PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
            versionName = info.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(this.getApplicationContext());
        strategy.setAppPackageName(getPackageName());
        strategy.setAppVersion(versionName);
        CrashReport.initCrashReport(this.getApplicationContext(), "001b121efb", true, strategy);
    }

    private void init() {
        // 打印日志
        StringBuffer param = new StringBuffer();
        param.append("appid=" + getString(R.string.appId));
        param.append(",");
        // 设置使用v5+
        param.append(SpeechConstant.ENGINE_MODE + "=" + SpeechConstant.MODE_MSC);
        SpeechUtility.createUtility(SpeechApp.this, param.toString());
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.exit(0);
        Intent intent = new Intent(this, HomeActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        Log.d("uncaughtException", "uncaughtException: ");
    }

    //    public static void hookWebView(){
//        int sdkInt = Build.VERSION.SDK_INT;
//        try {
//            Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
//            Field field = factoryClass.getDeclaredField("sProviderInstance");
//            field.setAccessible(true);
//            Object sProviderInstance = field.get(null);
//            if (sProviderInstance != null) {
//                Log.i(TAG,"sProviderInstance isn't null");
//                return;
//            }
//
//            Method getProviderClassMethod;
//            if (sdkInt > 22) {
//                getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
//            } else if (sdkInt == 22) {
//                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
//            } else {
//                Log.i(TAG,"Don't need to Hook WebView");
//                return;
//            }
//            getProviderClassMethod.setAccessible(true);
//            Class<?> factoryProviderClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
//            Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
//            Constructor<?> delegateConstructor = delegateClass.getDeclaredConstructor();
//            delegateConstructor.setAccessible(true);
//            if(sdkInt < 26){//低于Android O版本
//                Constructor<?> providerConstructor = factoryProviderClass.getConstructor(delegateClass);
//                if (providerConstructor != null) {
//                    providerConstructor.setAccessible(true);
//                    sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance());
//                }
//            } else {
//                Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD");
//                chromiumMethodName.setAccessible(true);
//                String chromiumMethodNameStr = (String)chromiumMethodName.get(null);
//                if (chromiumMethodNameStr == null) {
//                    chromiumMethodNameStr = "create";
//                }
//                Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass);
//                if (staticFactory!=null){
//                    sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance());
//                }
//            }
//
//            if (sProviderInstance != null){
//                field.set("sProviderInstance", sProviderInstance);
//                Log.i(TAG,"Hook success!");
//            } else {
//                Log.i(TAG,"Hook failed!");
//            }
//        } catch (Throwable e) {
//            Log.w(TAG,e);
//        }
//    }

    public static void hookWebView(){

        int sdkInt = Build.VERSION.SDK_INT;

        try {

            Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");

            Field field = factoryClass.getDeclaredField("sProviderInstance");

            field.setAccessible(true);

            Object sProviderInstance = field.get(null);

            if (sProviderInstance != null) {

                Log.i(TAG,"sProviderInstance isn't null");

                return;

            }



            Method getProviderClassMethod;

            if (sdkInt > 22) {

                getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");

            } else if (sdkInt == 22) {

                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");

            } else {

                Log.i(TAG,"Don't need to Hook WebView");

                return;

            }

            getProviderClassMethod.setAccessible(true);

            Class<?> factoryProviderClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);

            Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");

            Constructor<?> delegateConstructor = delegateClass.getDeclaredConstructor();

            delegateConstructor.setAccessible(true);

            if(sdkInt < 26){//低于Android O版本

                Constructor<?> providerConstructor = factoryProviderClass.getConstructor(delegateClass);

                if (providerConstructor != null) {

                    providerConstructor.setAccessible(true);

                    sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance());

                }

            } else {

                Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD");

                chromiumMethodName.setAccessible(true);

                String chromiumMethodNameStr = (String)chromiumMethodName.get(null);

                if (chromiumMethodNameStr == null) {

                    chromiumMethodNameStr = "create";

                }

                Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass);

                if (staticFactory!=null){

                    sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance());

                }

            }



            if (sProviderInstance != null){

                field.set("sProviderInstance", sProviderInstance);

                Log.i(TAG,"Hook success!");

            } else {

                Log.i(TAG,"Hook failed!");

            }

        } catch (Throwable e) {

            Log.w(TAG,e);

        }

    }
}
